home *** CD-ROM | disk | FTP | other *** search
- /*
- * Displays differences between two ASCII files
- *
- * Options:
- * -d = Inhibit display of differences
- * -l = Inhibit display of line numbers
- * r=num = Minimum # lines to re-syncronize
- *
- * Copyright 1988-1994 Dave Dunfield
- * All rights reserved.
- *
- * Permission granted for personal (non-commercial) use only.
- *
- * Compile command: cc diff -fop
- */
- #include <stdio.h>
-
- #define LINE_SIZE 100 /* maximum size of input lines */
- #define MAX_DIFF 200 /* maximum number of different lines */
-
- char ft1[MAX_DIFF][LINE_SIZE], ft2[MAX_DIFF][LINE_SIZE];
-
- unsigned r1 = 0, r2 = 0, w1 = 0, w2 = 0, l1, l2;
- unsigned resync = 2, diffs = 0;
-
- char diff = -1, line = -1;
-
- char *fn1, *fn2;
- FILE *fp1, *fp2;
-
- /*
- * Main program, compare files
- */
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char *ptr;
-
- l2 = 0;
- for(l1 = 1; l1 < argc; ++l1) {
- ptr = argv[l1];
- switch((tolower(*ptr++) << 8) | tolower(*ptr++)) {
- case 'r=' : /* minimum # lines to resync */
- resync = get_num(ptr);
- break;
- case '-d' : /* inhibit display of differences */
- diff = 0;
- break;
- case '-l' : /* inhibit display of line numbers */
- line = 0;
- break;
- default: /* filename to compare */
- if(!(fp2 = fopen(fn2 = argv[l1], "r"))) {
- fprintf(stderr, "%s: Unable to open\n", fn2);
- exit(-1); }
- if(!l2++) {
- fn1 = fn2;
- fp1 = fp2; } } }
-
- if(l2 != 2) {
- fputs("\nUse: diff <file1> <file2> [-d -l r=#lines]\n\nCopyright 1988-1994 Dave Dunfield\nAll rights reserved.\n", stderr);
- exit(-1); }
-
- l1 = l2 = 1;
- for(;;) {
- fill_buffer();
- if((r1 == w1) || (r2 == w2)) {
- show_changed(w1, w2);
- if(diffs)
- fprintf(stdout,"%u differences.\n", diffs);
- else
- fprintf(stdout,"Files match exactly.\n");
- exit(diffs); }
- if(equal(ft1[r1], ft2[r2])) {
- r1 = (r1 + 1) % MAX_DIFF;
- r2 = (r2 + 1) % MAX_DIFF;
- ++l1; ++l2;
- continue; }
- scan_buffer(); }
- }
-
- /*
- * Fill up the buffer with lines from the input file
- */
- fill_buffer()
- {
- register int j1, j2;
-
- while((j1 = (w1 + 1) % MAX_DIFF) != r1) {
- if(!fgets(ft1[w1], LINE_SIZE, fp1))
- break;
- w1 = j1; }
- while((j2 = (w2 + 1) % MAX_DIFF) != r2) {
- if(!fgets(ft2[w2], LINE_SIZE, fp2))
- break;
- w2 = j2; }
- }
-
- /*
- * Scan the buffer looking for a pattern
- */
- scan_buffer()
- {
- int i, i1, i2, j1, j2;
- char flag;
-
- i1 = r1;
- i2 = r2;
- fill_buffer();
- do { /* scan with this portion */
- j1 = i1;
- j2 = i2;
- do {
- flag = 0;
- if(j2 != w2) { /* we can check this one */
- flag = -1;
- if(equal(ft1[i1], ft2[j2]) && (i=test_next(i1, j2))) {
- show_changed(i1, j2);
- r1 = (r1 + i) % MAX_DIFF;
- r2 = (r2 + i) % MAX_DIFF;
- l1 += i; l2 += i;
- return; }
- j2 = (j2 + 1) % MAX_DIFF; }
- if(j1 != w1) { /* we can check this one */
- flag = -1;
- if(equal(ft1[j1], ft2[i2]) && (i=test_next(j1, i2))) {
- show_changed(j1, i2);
- r1 = (r1 + i) % MAX_DIFF;
- r2 = (r2 + i) % MAX_DIFF;
- l1 += i; l2 += i;
- return; }
- j1 = (j1 + 1) % MAX_DIFF; } }
- while(flag);
- if(i1 != w1) { /* More lines in buffer */
- i1 = (i1 + 1) % MAX_DIFF;
- flag = -1; }
- if(i2 != w2) { /* More lines in buffer */
- i2 = (i2 + 1) % MAX_DIFF;
- flag = -1; } }
- while(flag);
-
- /* Cannot accept any more data into buffers, check for overflow */
- if((((w1 + 1) % MAX_DIFF) == r1) || (((w2 + 1) % MAX_DIFF) == r2)) {
- fprintf(stdout,"Differences to great at %u < > %u\n", l1, l2);
- exit(-1); }
- /* Buffers not full, must be end of file */
- show_changed(w1, w2);
- }
-
- /*
- * Test that the next "resync" entries match
- */
- test_next(i1, i2)
- unsigned i1, i2;
- {
- int i;
-
- for(i=1; i < resync; ++i) {
- i1 = (i1 + 1) % MAX_DIFF;
- i2 = (i2 + 1) % MAX_DIFF;
- if((i1 == w1) || (i2 == w2))
- return i;
- if(!equal(ft1[i1], ft2[i2]))
- return 0; }
- return i;
- }
-
- /*
- * Display the changed lines & reset read pointers
- */
- show_changed(i1, i2)
- unsigned i1, i2;
- {
- if((r1 != i1) || (r2 != i2)) {
- ++diffs;
- if(line)
- fprintf(stdout,"*** %s(%u) < > %s(%u) ***\n", fn1, l1, fn2, l2);
- while(r1 != i1) {
- ++l1;
- if(diff)
- fprintf(stdout,"<%s\n", ft1[r1]);
- r1 = (r1 + 1) % MAX_DIFF; }
- while(r2 != i2) {
- ++l2;
- if(diff)
- fprintf(stdout,">%s\n", ft2[r2]);
- r2 = (r2 + 1) % MAX_DIFF; } }
- }
-
- /*
- * Get a decimal number from the command line
- */
- get_num(string)
- char *string;
- {
- register unsigned value;
- register char chr;
-
- value = 0;
- while(isdigit(chr = *string++))
- value = (value * 10) + (chr - '0');
-
- if(chr) {
- fputs("DIFF: Invalid number\n", stderr);
- exit(-1); }
-
- return value;
- }
-
- /*
- * Test for two strings equal
- */
- equal(str1, str2)
- char *str1, *str2;
- {
- register char c;
-
- while((c = *str1++) == *str2++) {
- if(!c)
- return 1; }
- return 0;
- }
-